#pragma once

#include <algorithm/shared/data/topology/geometry/Geometry.h>
#include <algorithm/shared/tool/stringHash/StringHash.hpp>

#include <boost/json.hpp>

#include <memory>
#include <string_view>

namespace solar::io::json::internal
{
    constexpr auto convertGeometryType(const GeometryType& type) -> std::string_view
    {
        switch (type)
        {
        case GeometryType::kGeometryCylinder:
            return "cylinder";
        case GeometryType::kGeometryCylinder3D:
            return "cylinder_3d";
        case GeometryType::kGeometryRectangle:
            return "rectangle";
        case GeometryType::kGeometryRectangle3D:
            return "rectangle_3d";
        default:
            throw "Unknown GeometryType";
        }
    }

    constexpr auto convertGeometryType(const std::string_view name) -> GeometryType
    {
        switch (hash(name.data()))
        {
        case hash("cylinder"):
            return GeometryType::kGeometryCylinder;
        case hash("cylinder_3d"):
            return GeometryType::kGeometryCylinder3D;
        case hash("rectangle"):
            return GeometryType::kGeometryRectangle;
        case hash("rectangle_3d"):
            return GeometryType::kGeometryRectangle3D;
        default:
            throw "Unknown GeometryType";
        }
    }
} // namespace solar::internal

namespace solar
{
    // NOLINTBEGIN(readability-identifier-naming)
    void tag_invoke(const boost::json::value_from_tag&, boost::json::value& json_value,
                    const std::shared_ptr<Geometry>& geometry);
    auto tag_invoke(const boost::json::value_to_tag<std::shared_ptr<Geometry>>&,
                    const boost::json::value& json_value) -> std::shared_ptr<Geometry>;
    // NOLINTEND(readability-identifier-naming)
} // namespace solar
